热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

听筒|声道_uniapp实战笔记实现语音播放功能

篇首语:本文由编程笔记#小编为大家整理,主要介绍了uniapp实战笔记实现语音播放功能相关的知识,希望对你有一定的参考价值。市面上

篇首语:本文由编程笔记#小编为大家整理,主要介绍了uniapp实战笔记实现语音播放功能相关的知识,希望对你有一定的参考价值。



市面上其实已经有很多成熟的产品实现了语音功能,以微信语音功能为例:即使手机处于静音模式,仍然能播放语音;语音播放能在扬声器和听筒模式之间来回切换,在播放时监测到用户耳朵靠近会熄灭屏幕,如果此时的播放模式为扬声器播放,还会将播放模式切换至听筒播放。

【uniapp实战笔记】实现语音播放功能_uniapp

由此,我们整理出以下需求点:

需求点

  1. 语音播放不跟随系统铃声模式。
  2. 语音播放支持扬声器/听筒播放。
  3. 扬声器模式下播放检测到距离接近需要息屏(防误触)并实时转换为听筒播放,距离远离需亮屏并转回扬声器播放。
  4. 听筒模式下播放检测距离变化不需要切换播放声道,但距离接近需要息屏(防误触),距离远离需要亮屏。


分析需求

首先,需要明确一点,语音播放支持扬声器/听筒播放,那就只能使用 plus.audio.createPlayer 来实现。

而切换播放声道,则可以使用 plus.audio.createPlayer 创建出来实例的 ​​setRoute()​​ 方法。

基于3、4点需求,明确在播放语音时需要添加距离监听器,可以使用 ​​plus.proximity.watchProximity​​ 来实时监听设备接近距离。

最后一个接近息屏,远离亮屏的需求,先把前面的做了,再看看如何实现吧。


实现

this.playMode:播放声道(扬声器 0,听筒 1)

this.playState:play回调中播放参数

1、距离监听器

this.watchProximity = plus.proximity.watchProximity((distance) =>
/**
* ios端接近为0,远离为Infinity
* android端接近为0,远离为5
*/
if (this.playMode === 0)
// 扬声器模式下,需要对声道进行实时修改
this.voicePlayer.pause();
if (distance !== 0)
// 扬声器
this.voicePlayer.setRoute(0);
else
// 听筒
this.voicePlayer.setRoute(1);

this.voicePlayer.resume();

);

2、初始化播放器

this.voicePlayer = plus.audio.createPlayer( src: xxx );
this.voicePlayer.setRoute(this.playMode);
// 监听自然播放完成
this.voicePlayer.addEventListener(ended, () =>
// 销毁正在监听设备距离的监听器
if (this.watchProximity)
plus.proximity.clearWatch(this.watchProximity);
this.watchProximity = null;

console.log(播放完毕了);
);
// 监听音频可以开始播放事件
this.voicePlayer.addEventListener(play, () =>
// 首次播放时会执行两次回调
if (this.playState !== 2)
// plus.audio.ROUTE_SPEAKER:扬声器 0
// plus.audio.ROUTE_EARPIECE:听筒 1
this.voicePlayer.setRoute(this.playMode);
this.playState++;

);
// 监听音频播放错误事件
this.voicePlayer.addEventListener(error, (err) =>
console.log(报错err, err);
// 销毁正在监听设备距离的监听器
if (this.watchProximity)
plus.proximity.clearWatch(this.watchProximity);
this.watchProximity = null;

);

3、播放

// 在正确的地方调用播放
this.voicePlayer.play();

播放后,发现语音在 iOS 端,是默认存在接近息屏,远离亮屏的现象(默认行为)。但 Android 端在播放时,始终是亮屏的,这样看来 Android 端还需要自己实现。

播放时,初始播放模式为扬声器模式,接近切换为听筒,远离切换回扬声器,在 iOS 端是能完美表现的,切换无延迟,而Android 端切换是存在延迟的,好在延迟不影响播放。

播放时,初始播放模式为听筒模式,Android 端第一次播放音频会存在几秒钟的卡顿延迟,且该卡顿是占播放时间的。这也就是说第一次播放是不完整的,目前也没有什么比较好的方案解决(暂时搁置)。


Android端实现播放时接近息屏,远离亮屏

这该如何下手呢?

博主查阅了 plus 几乎所有的 API,都没有能找到相关的内容,看来只能上 Android 官网找了。

直接上 Android 官网找跟电源相关的 API,发现了 ​​PowerManager​​​,在其中找到了一个电平模式 ​​PROXIMITY_SCREEN_OFF_WAKE_LOCK​​。

具体如下:【uniapp实战笔记】实现语音播放功能_ios_02

这不就是我想要的答案吗?

事不宜迟,说干就干!

由于 PowerManager 电源管理类是属于全局唯一的,所以使用也不能像播放音频那样随随便便 new 一个实例出来,需要借助 Android 的主实例对象plus.android.runtimeMainActivity() 来调用获取。

this.platform:当前手机平台

this.wakeLock:唤醒锁

// Android端需要设置唤醒模式才能在接近传感器激活时关闭屏幕,iOS端自带了
if (this.platform === android)
let main = plus.android.runtimeMainActivity();
let COntext= plus.android.importClass(android.content.Context);
let PowerManager = plus.android.importClass(android.os.PowerManager);
let pm = main.getSystemService(Context.POWER_SERVICE);
// 32代表PROXIMITY_SCREEN_OFF_WAKE_LOCK,唤醒锁定电平:当接近传感器激活时关闭屏幕
let status = pm.isWakeLockLevelSupported(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
// 系统支持该唤醒模式
if (status)
this.wakeLock = pm.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, TAG);
this.wakeLock.acquire();

在刚刚初始化播放器时添加的监听事件中,增加对唤醒模式资源的释放。

// 监听自然播放完成
this.voicePlayer.addEventListener(ended, () =>
// 销毁正在监听设备距离的监听器
if (this.watchProximity)
plus.proximity.clearWatch(this.watchProximity);
this.watchProximity = null;

// 释放唤醒锁
if (this.wakeLock)
this.wakeLock.release();
this.wakeLock = null;

console.log(播放完毕了);
);
// 监听音频播放错误事件
this.voicePlayer.addEventListener(error, (err) =>
console.log(报错err, err);
// 释放唤醒锁
if (this.wakeLock)
this.wakeLock.release();
this.wakeLock = null;

// 销毁正在监听设备距离的监听器
if (this.watchProximity)
plus.proximity.clearWatch(this.watchProximity);
this.watchProximity = null;

);

至此,所有的需求都圆满完成了!


总结

随着对 uniapp 的深入了解,越来越多功能点的实现,开发人员不止需要把视角放在前端,还需要转战到 Android、iOS 官方查阅相关的 API 文档才能实现。

按照这个趋势,博主认为凡是手机系统底层实现了的功能,但 uniapp 未实现的,都可以通过 plus.android 或者 plus.ios 通过调用相关功能类来实现,这泥潭算是越陷越深了。

一起继续加油,Keep learning…


下期继续给大家分享uni-app实战中的点点滴滴,敬请期待~

欢迎各位关注、留言,大家的支持就是我的动力!


推荐阅读
  • 问题描述现在,不管开发一个多大的系统(至少我现在的部门是这样的),都会带一个日志功能;在实际开发过程中 ... [详细]
  • 深入理解线程池及其基本实现
    本文探讨了线程池的概念、优势及其在Java中的应用。通过实例分析不同类型的线程池,并指导如何构建一个简易的线程池。 ... [详细]
  • Hanks博士是一位著名的生物技术专家,他的儿子Hankson对数学有着浓厚的兴趣。最近,Hankson遇到了一个有趣的数学问题,涉及求解特定条件下的正整数x,而不使用传统的辗转相除法。 ... [详细]
  • Android 中的布局方式之线性布局
    nsitionalENhttp:www.w3.orgTRxhtml1DTDxhtml1-transitional.dtd ... [详细]
  • Zabbix自定义监控与邮件告警配置实践
    本文详细介绍了如何在Zabbix中添加自定义监控项目,配置邮件告警功能,并解决测试告警时遇到的邮件不发送问题。 ... [详细]
  • 2023年,Android开发前景如何?25岁还能转行吗?
    近期,关于Android开发行业的讨论在多个平台上热度不减,许多人担忧其未来发展。本文将探讨当前Android开发市场的现状、薪资水平及职业选择建议。 ... [详细]
  • 二维码的实现与应用
    本文介绍了二维码的基本概念、分类及其优缺点,并详细描述了如何使用Java编程语言结合第三方库(如ZXing和qrcode.jar)来实现二维码的生成与解析。 ... [详细]
  • importjava.io.*;importjava.util.*;publicclass五子棋游戏{staticintm1;staticintn1;staticfinalintS ... [详细]
  • pypy 真的能让 Python 比 C 还快么?
    作者:肖恩顿来源:游戏不存在最近“pypy为什么能让python比c还快”刷屏了,原文讲的内容偏理论,干货比较少。我们可以再深入一点点,了解pypy的真相。正式开始之前,多唠叨两句 ... [详细]
  • 本文介绍了读写锁(RWMutex)的基本概念、实现原理及其在Go语言中的应用。读写锁允许多个读操作并发执行,但在写操作时确保互斥,从而提高并发性能。 ... [详细]
  • 本文详细介绍了C++中的构造函数,包括其定义、特点以及如何通过构造函数进行对象的初始化。此外,还探讨了转换构造函数的概念及其在不同情境下的应用,以及如何避免不必要的隐式类型转换。 ... [详细]
  • 在开发iOS应用时,面对不同状态(如数据加载成功、无数据、未登录、网络异常等)的界面管理,如何实现既高效又美观的用户体验?本文探讨了几种最佳实践方法。 ... [详细]
  • HTML前端开发:UINavigationController与页面间数据传递详解
    本文详细介绍了如何在HTML前端开发中利用UINavigationController进行页面管理和数据传递,适合初学者和有一定基础的开发者学习。 ... [详细]
  • 在Android平台中,播放音频的采样率通常固定为44.1kHz,而录音的采样率则固定为8kHz。为了确保音频设备的正常工作,底层驱动必须预先设定这些固定的采样率。当上层应用提供的采样率与这些预设值不匹配时,需要通过重采样(resample)技术来调整采样率,以保证音频数据的正确处理和传输。本文将详细探讨FFMpeg在音频处理中的基础理论及重采样技术的应用。 ... [详细]
  • 在Android 4.4系统中,通过使用 `Intent` 对象并设置动作 `ACTION_GET_CONTENT` 或 `ACTION_OPEN_DOCUMENT`,可以从相册中选择图片并获取其路径。具体实现时,需要为 `Intent` 添加相应的类别,并处理返回的 Uri 以提取图片的文件路径。此方法适用于需要从用户相册中选择图片的应用场景,能够确保兼容性和用户体验。 ... [详细]
author-avatar
开心宝2502869253
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有